package com.test.config;

import com.test.config.shiro.cache.RedisCacheManager;
import com.test.config.shiro.jwtConfig.JwtFilter;
import com.test.config.shiro.realms.MyCustomerRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;

/**
 * 配置shiro整合springboot的配置
 * * 1.配置shiroFilter 将所有的请求交给shiro管理
 * * 2.配置SecurityManager,并且将安全管理器作为参数交给shiroFilter管理
 * * 3.配置自定义的realm,作为参数交给SecurityManager管理
 */

@Configuration  //作为Springboot的配置类 @Bean将返回值作为Springboot中的bean
public class ShiroConfig {
    //1.配置shiroFilter 将所有的请求交给shiro管理
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //给shiroFilterFactoryBean设置安全管理器,从bean中获取到的传递过来的
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //配置默认认证界面路径 , shiro默认拦截受限资源之后,没有权限会自动跳转到login的路劲,此处可以自定义配置
        //shiroFilterFactoryBean.setLoginUrl("/login.jsp");

        //设置自定义的jwtFilter
        HashMap<String, Filter> filterMap = new HashMap<>();
        filterMap.put("jwt", new JwtFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        //配置系统受限资源,是一个map集合,key是资源页面,value是限制还是放行
        HashMap<String, String> map = new HashMap<>();
        map.put("/user/login", "anon");  //anno设置为公共资源,不需要认证,注意不受限的资源要放在上边
        map.put("/user/registry", "anon");  //用户通过注册页面,注册信息跳转到注册接口,需要放行
        map.put("/registry.jsp", "anon");   //用户注册页面,为公共资源
        //map.put("/**", "authc");   //authc是需要认证和授权的 ,所有的目录都需要认证之后才能访问,应该放行登录页面

        //拦截请求使用我们自己定义的拦截器
        map.put("/**", "jwt");

        //将规格交给shiro
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

    //2.配置SecurityManager,并且将安全管理器作为参数交给shiroFilter管理 web环境下 创建DefaultWebSecurityManager
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

        //给安全管理器设置自定义的realm,从bean中获取到的传递过来的
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }

    //3.配置自定义的realm,作为参数交给SecurityManager管理
    @Bean
    public Realm getRealm() {
        //自定义的realm,创建对象返回,放入到springboot的容器中
        MyCustomerRealm myCustomerRealm = new MyCustomerRealm();

       /* //修改凭证校验匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");  //设置加密算法为MD5
        hashedCredentialsMatcher.setHashIterations(10);   //设置散次列  注册时设置了 10次  散次列

        //将凭证校验匹配器,设置给自定义的realm
        myCustomerRealm.setCredentialsMatcher(hashedCredentialsMatcher);*/

        //开启缓存管理  避免了多次反复查询数据库,这是内存缓存,程序停止缓存就没有了,可以用redis代替
        //myCustomerRealm.setCacheManager(new EhCacheManager()); //使用ehCache 缓存  实现CacheManager (shiro的) 实现的缓存,自定义的redis缓存也可以通过实现CacheManager做shiro缓存

        myCustomerRealm.setCacheManager(new RedisCacheManager()); //自定义的redis缓存也可以通过实现CacheManager做shiro缓存
        myCustomerRealm.setCachingEnabled(true);   //开启缓存
        myCustomerRealm.setAuthenticationCachingEnabled(true);  //开启认证缓存
        myCustomerRealm.setAuthenticationCacheName("authenticationCache");  //设置认证缓存的名称,方便查找 (默认名称:authentication + 自定义realm名称)
        myCustomerRealm.setAuthorizationCachingEnabled(true);   //开启授权缓存
        myCustomerRealm.setAuthorizationCacheName("authorizationCache");  //设置授权缓存名称

        return myCustomerRealm;
    }
}
